package com.ruoyi.sea.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.mqtt.MqttCustomerClient;
import com.ruoyi.sea.domain.*;
import com.ruoyi.sea.service.ISeaAlarmService;
import com.ruoyi.sea.service.ISeaDataRangeService;
import com.ruoyi.sea.service.ISeaDeviceService;
import com.ruoyi.sea.service.ISeaValueService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class TCPClientServiceImpl implements ApplicationRunner {

    // 温度
    private static float temp = 0F;
    // COD
    private static float cod = 0F;
    // ph
    private static float ph = 0F;
    // 余氯
    private static float residualChlorine = 0F;
    // 电导率
    private static float conductivity = 0F;
    // 氨氮
    private static float ammoniaNitrogen = 0F;
    private static String deviceStatus = "normal";
    @Resource
    ISeaDataRangeService seaDataRangeService;
    @Resource
    ISeaAlarmService seaAlarmService;
    @Resource
    private MqttCustomerClient mqttCustomerClient;
    @Resource
    private ISeaValueService seaValueService;
    @Resource
    private RedisCache redisCache;
    @Resource
    private ISeaDeviceService seaDeviceService;

    @Override
    //  启动时执行
    public void run(ApplicationArguments args) throws Exception {
        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            //  定时任务执行
            public void run() {
                // 获取数据
                getRealTimeData02();
                // 读取硬件设施数据
                JSONObject json = new JSONObject();
                /**
                 * cod_redis
                 */
                json.put("temp", temp);//将当前温度temp存入json对象
                Float temp_redis = redisCache.getCacheObject("temp");//从Redis获取缓存温度值temp_redis（若不存在则设为0）
                if (temp_redis == null) {
                    temp_redis = 0F;
                }
                json.put("temp_compare", Float.compare(temp, temp_redis));// 比较当前温度temp和Redis缓存温度temp_redis

                /**
                 * COD
                 */
                json.put("cod", cod);
                Float cod_redis = redisCache.getCacheObject("cod");
                if (cod_redis == null) {
                    cod_redis = 0F;
                }
                json.put("cod_compare", Float.compare(cod, cod_redis));

                /**
                 * ph
                 */
                json.put("ph", ph);
                Float ph_redis = redisCache.getCacheObject("ph");
                if (ph_redis == null) {
                    ph_redis = 0F;
                }
                json.put("ph_compare", Float.compare(ph, ph_redis));

                /**
                 * 余氯
                 */
                json.put("residualChlorine", residualChlorine);
                Float residualChlorine_redis = redisCache.getCacheObject("residualChlorine");
                if (residualChlorine_redis == null) {
                    residualChlorine_redis = 0F;
                }
                json.put("residualChlorine_compare", Float.compare(residualChlorine, residualChlorine_redis));

                /**
                 * 电导率
                 */
//                Integer conductivity = getresidualChlorine();
                json.put("conductivity", conductivity);
                Float conductivity_redis = redisCache.getCacheObject("conductivity");
                if (conductivity_redis == null) {
                    conductivity_redis = 0F;
                }
                json.put("conductivity_compare", Float.compare(conductivity, conductivity_redis));

                /**
                 *  氨氮
                 */
//                Float ammonia_nitrogen = getAmmoniaNitrogen();
                json.put("ammoniaNitrogen", ammoniaNitrogen);
                Float ammoniaNitrogen_redis = redisCache.getCacheObject("ammoniaNitrogen");
                if (ammoniaNitrogen_redis == null) {
                    ammoniaNitrogen_redis = 0F;
                }
                json.put("ammoniaNitrogen_compare", Float.compare(ammoniaNitrogen, ammoniaNitrogen_redis));

//                mqttCustomerClient.pushlish("sea_status", json.toJSONString());
//                getRealTimeData("1L");
            }
        };
        // 3秒执行一次
        timer.schedule(task, 0, 3000);
    }

    //  获取并缓存第三方API的访问令牌（token）
    public String getToken() {
        String token = redisCache.getCacheObject("token");
        if (StringUtils.isBlank(token)) {
            // 创建HttpClient实例
            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                // 创建HttpGet实例并设置URL
                HttpGet httpGet = new HttpGet("http://192.168.217.195/api/getToken?loginName=vh250527zyjs&password=vh250527zyjs");
                // 执行请求并获取响应
                try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                    // 获取响应实体
                    String responseBody = EntityUtils.toString(response.getEntity());
                    ObjectMapper mapper = new ObjectMapper();
                    JsonNode jsonNode = mapper.readTree(responseBody);
                    token = jsonNode.get("data").get("token").toString().replaceAll("\"", "");
                    redisCache.setCacheObject("token", token, 1, TimeUnit.HOURS);
                }
            } catch (Exception e) {
                System.out.println("————————————————————————————————————远程连接失败————————————————————————————————————");
                e.printStackTrace();
            }
        }
        return token;
    }
    //http://192.168.217.195/api/data/getRealTimeData?deviceCode=
    /**
     * 数据获取 解析 储存
     * deviceCode
     */
    public void getRealTimeData(String deviceCode) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet("http://192.168.217.195/api/data/getRealTimeData?deviceCode=" + deviceCode);
        httpGet.addHeader("authorization", getToken());
        try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
            //将响应结果转换为字符串
            String responseBody = EntityUtils.toString(httpResponse.getEntity());
            //json
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(responseBody);
            //数据解析
            if (StringUtils.equals(jsonNode.get("code").toString(), "10000")) {
                JsonNode data = jsonNode.get("data");
                //替换双引号
                String deviceStatus = data.get("deviceStatus").toString().replaceAll("\"", "");
                if (StringUtils.equals(deviceStatus, "normal")) {
                    SeaDevice seaDevice = new SeaDevice();
                    //设置设备编号、状态
                    seaDevice.setCode(deviceCode);
                    seaDevice.setStatus("1");
                    //插入数据库
                    seaDeviceService.insertSeaDevice(seaDevice);
                }
                //解析六项指标
                WaterData waterData = analysisSixData(data);
                //使用mqtt推送给前端
                mqttCustomerClient.pushlish("sea_status", waterData.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 解析六项指标
     * @param dataItem
     */
    private WaterData analysisSixData(JsonNode dataItem) {
        WaterData waterData = new WaterData();
        dataItem.forEach(e -> {
            e.get("registerItem").forEach(t -> {
                String registerName = t.get("registerName").toString().replace("\"", "");
                String dataValue = t.get("data").toString().replace("\"", "");
                switch (registerName) {
                    case "温度":
                        float tempValue = Float.parseFloat(dataValue);
                        waterData.setTemperature(tempValue);
                        temp = tempValue;
                        break;
                    case "PH":
                        float phValue = Float.parseFloat(dataValue);
                        waterData.setPh(phValue);
                        ph = phValue;
                        break;
                    case "导电率":
                        float conductivityValue = Float.parseFloat(dataValue);
                        waterData.setConductivity(conductivityValue);
                        conductivity = conductivityValue;
                        break;
                    case "氨氮":
                        float ammoniaNitrogenValue = Float.parseFloat(dataValue);
                        waterData.setAmmoniaNitrogen(ammoniaNitrogenValue);
                        ammoniaNitrogen = ammoniaNitrogenValue;
                        break;
                    case "COD":
                        float codValue = Float.parseFloat(dataValue);
                        waterData.setCod(codValue);
                        cod = codValue;
                        break;
                    case "余氯":
                        float residualChlorineValue = Float.parseFloat(dataValue);
                        waterData.setResidualChlorine(residualChlorineValue);
                        residualChlorine = residualChlorineValue;
                        break;
                    default:
                        break;
                }
            });
        });
        return waterData;
    }

    //  通过HTTP请求第三方物联网平台API获取设备实时数据
    public void getRealTimeData02() {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            //创建httpGet获取url http://iot.lwbsq.com/api/data/getRealTimeData
            HttpGet httpGet = new HttpGet("http://iot.lwbsq.com/api/data/getRealTimeData");
            //获取getToken令牌
            httpGet.addHeader("authorization", getToken());
            //执行请求并获取响应
            try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
                String responseBody = EntityUtils.toString(httpResponse.getEntity());
                //将获取实体转换为json对象
                ObjectMapper mapper = new ObjectMapper();
                JsonNode jsonNode = mapper.readTree(responseBody);
                //解析数据
                if (StringUtils.equals(jsonNode.get("code").toString(), "1000")) {
                    JsonNode data = jsonNode.get("data").get(0);
                    //获取到转换为json的数据
                    log.info("把获取的数据转换为json格式" + data);
                    //设备状态 替换掉双引号
                    String deviceStatus = data.get("deviceStatus").toString().replaceAll("\"", "");
                    //更新设备状态
                    if (StringUtils.equals(deviceStatus, "normal")) {
                        SeaDevice seaDevice = new SeaDevice();
                        seaDevice.setId(1L);
                        seaDevice.setStatus("1");
                        seaDeviceService.updateSeaDevice(seaDevice);
                    }
                    //=====================================================================================
                    //解析数据 用forEach遍历获取数据
                    data.get("dataItem").forEach(e -> {
                        e.get("registerItem").forEach(t -> {
                            //温度
                            if (StringUtils.equals(t.get("registerName").toString().replace("\"", ""), "温度")) {
                                temp = Float.parseFloat(t.get("data").toString().replace("\"", ""));
                            }
                            //PH
                            if (StringUtils.equals(t.get("registerName").toString().replace("\"", ""), "PH")) {
                                ph = Float.parseFloat(t.get("data").toString().replace("\"", ""));
                            }
                            //导电率
                            if (StringUtils.equals(t.get("registerName").toString().replace("\"", ""), "导电率")) {
                                conductivity = Float.parseFloat(t.get("data").toString().replace("\"", ""));
                            }
                            //氨氮
                            if (StringUtils.equals(t.get("registerName").toString().replace("\"", ""), "氨氮")) {
                                ammoniaNitrogen = Float.parseFloat(t.get("data").toString().replace("\"", ""));
                            }
                            //COD
                            if (StringUtils.equals(t.get("registerName").toString().replace("\"", ""), "COD")) {
                                cod = Float.parseFloat(t.get("data").toString().replace("\"", ""));
                            }
                            //余氯
                            if (StringUtils.equals(t.get("registerName").toString().replace("\"", ""), "余氯")) {
                                residualChlorine = Float.parseFloat(t.get("data").toString().replace("\"", ""));
                            }
                        });
                    });
                }
            }
        } catch (IOException e) {
            System.out.println("————————————————————————————————————远程连接失败————————————————————————————————————");
            e.printStackTrace();//打印在HTTP请求请求过程中发生的异常信息
        }


        //以下是处理实时环境监测数据并触发异常报警
        SeaValue seaValue = new SeaValue();
        seaValue.setId(1L);
        // 单位
        String tempUnit = "°C";
        String salinityUnit = "μs/cm";
        String conductivityUnit = "mg/L";
        String otherUnit = "mg/L";
        // 获取最新报警阈值
        SeaDataRange dataRange = seaDataRangeService.selectSeaDataRangeById(1L);

        /**
         * 温度
         */
        seaValue.setWaterTemperature(temp);
        redisCache.setCacheObject("temp", temp);
        // 判断温度是否在阈值外
        if (dataRange.getWaterTemperatureTop() < temp || temp < dataRange.getWaterTemperatureBottom()) {
            // 温度异常
            insetAlarm(1L,
                    "温度异常",
                    temp + "",
                    dataRange.getWaterTemperatureBottom() + tempUnit + " - " + dataRange.getWaterTemperatureTop() + tempUnit,
                    "四川省泸州市龙马潭区");
        }

        /**
         * COD
         */
        seaValue.setCod(cod);
        redisCache.setCacheObject("cod", cod);
        // 判断盐是否在阈值外
        if (dataRange.getCodTop() < cod || cod < dataRange.getCodBottom()) {
            // 盐异常
            insetAlarm(1L,
                    "COD异常",
                    cod + "",
                    dataRange.getCodBottom() + salinityUnit + " - " + dataRange.getCodTop() + salinityUnit,
                    "四川省泸州市龙马潭区");
        }

        /**
         * PH
         */
        seaValue.setPh(ph);
        redisCache.setCacheObject("ph", ph);
        // 判断ph是否在阈值外
        // BigDecimal 需要处理
        BigDecimal currentPh = new BigDecimal(String.valueOf(ph));
        BigDecimal bottom = new BigDecimal(String.valueOf(dataRange.getPhBottom()));
        BigDecimal top = new BigDecimal(String.valueOf(dataRange.getPhTop()));
        if (currentPh.compareTo(bottom) < 0 || currentPh.compareTo(top) > 0) {
            insetAlarm(1L,
                    "ph异常",
                    currentPh.toString(),
                    bottom + "-" + top,
                    "四川省泸州市龙马潭区");
        }

        /**
         * 余氯
         */
        seaValue.setResidualChlorine(residualChlorine);
        redisCache.setCacheObject("residualChlorine", residualChlorine);
        currentPh = new BigDecimal(String.valueOf(residualChlorine));
        bottom = new BigDecimal(String.valueOf(dataRange.getResidualChlorineBottom()));
        top = new BigDecimal(String.valueOf(dataRange.getResidualChlorineTop()));
        // 判断余氯是否在阈值外
        if (currentPh.compareTo(bottom) < 0 || currentPh.compareTo(top) > 0) {
            // 余氯异常
            insetAlarm(1L,
                    "余氯异常",
                    residualChlorine + "",
                    dataRange.getResidualChlorineBottom() + conductivityUnit + " - " + dataRange.getResidualChlorineTop() + conductivityUnit,
                    "四川省泸州市龙马潭区");
        }

        /**
         * 电导率
         */
        seaValue.setConductivity(conductivity);
        redisCache.setCacheObject("conductivity", conductivity);
        currentPh = new BigDecimal(String.valueOf(conductivity));
        bottom = new BigDecimal(String.valueOf(dataRange.getConductivityBottom()));
        top = new BigDecimal(String.valueOf(dataRange.getConductivityTop()));
        // 判断电导率是否在阈值外
        if (currentPh.compareTo(bottom) < 0 || currentPh.compareTo(top) > 0) {
            // 溶解氧异常
            insetAlarm(1L,
                    "电导率异常",
                    conductivity + "",
                    dataRange.getConductivityBottom() + otherUnit + " - " + dataRange.getConductivityTop() + otherUnit,
                    "四川省泸州市龙马潭区");
        }

        /**
         * 氨氮
         */
        seaValue.setAmmoniaNitrogen(ammoniaNitrogen);
        redisCache.setCacheObject("ammoniaNitrogen", ammoniaNitrogen);
        currentPh = new BigDecimal(String.valueOf(ammoniaNitrogen));
        bottom = new BigDecimal(String.valueOf(dataRange.getAmmoniaNitrogenBottom()));
        top = new BigDecimal(String.valueOf(dataRange.getAmmoniaNitrogenTop()));
        if (currentPh.compareTo(bottom) < 0 || currentPh.compareTo(top) > 0) {
            // 磷酸盐异常
            insetAlarm(1L,
                    "氨氮异常",
                    ammoniaNitrogen + "",
                    dataRange.getAmmoniaNitrogenBottom() + otherUnit + " - " + dataRange.getAmmoniaNitrogenTop() + otherUnit,
                    "四川省泸州市龙马潭区");
        }
        // 保存实施记录
        if (seaValue.getPh() != 0F) {
            // 设备编号
            seaValue.setDeviceCode("NEU0121");
            seaValueService.insertSeaValue(seaValue);
        }

    }

    //==========================================================================
    // 溶氧量约为conductivity千分之6
    private int getConductivity() {
        BigDecimal increment = new BigDecimal("0.006");
        return new BigDecimal(conductivity).multiply(increment).intValue();
    }

    // 磷酸盐约为conductivity十万分之8
    private float getammonia_nitrogen() {
        BigDecimal increment = new BigDecimal("0.000008");
        return new BigDecimal(conductivity).multiply(increment).setScale(1, BigDecimal.ROUND_UP).floatValue();
    }

    // 硅酸盐 conductivity 十万分之1
    private float getAmmoniaNitrogen() {
        BigDecimal increment = new BigDecimal("0.00001");
        return new BigDecimal(conductivity).multiply(increment).setScale(1, BigDecimal.ROUND_UP).floatValue();
    }

    // 硝酸盐约为conductivity万分之15
    private float getNitrate() {
        BigDecimal increment = new BigDecimal("0.00015");
        return new BigDecimal(conductivity).multiply(increment).setScale(1, BigDecimal.ROUND_UP).floatValue();
    }

    // 盐度为conductivity的千分之1
    private int getSalinty() {
        BigDecimal increment = new BigDecimal("0.001");
        return new BigDecimal(conductivity).multiply(increment).intValue();

    }

    //  插入报警信息
    public void insetAlarm(Long deviceId, String msg, String value, String standard, String coordinate) {
        SeaAlarm seaAlarm = new SeaAlarm();
        seaAlarm.setDeviceId(deviceId);
        seaAlarm.setMsg(msg);
        seaAlarm.setValue(value);
        seaAlarm.setstandard(standard);
        seaAlarm.setCoordinate(coordinate);
        seaAlarm.setCreateTime(new Date());
        int flag = seaAlarmService.insertSeaAlarm(seaAlarm);
        if (flag > 0) {
            log.info("警告 插入成功");
        } else {
            log.info("警告 插入失败");
        }
    }

    public void fakeMethods() {
    }
}
